package org.estela.vm;

import static org.estela.vm.Instruction.INVOKE_FUNCTION;
import static org.estela.vm.Instruction.LDC;
import static org.estela.vm.Instruction.PRINT;
import static org.estela.vm.Instruction.RETURN;

import java.util.Stack;

public class ExecutionFrame {

	private EstelaVM _vm;
	
	private Instruction[] _frame;
	
	private Stack _stack;
	
	public ExecutionFrame(EstelaVM vm, Instruction[] frame) {
		this(vm, frame, new Stack());
	}

	public ExecutionFrame(EstelaVM vm, Instruction[] frame, Stack stack) {
		_vm = vm;
		_frame = frame;
		_stack = stack;
	}

	public void execute() {
		for(int i=0;i<_frame.length;i++) {
			switch (_frame[i].getCode()) {
			case LDC:
				_stack.push(_frame[i].getArguments()[0]);
				break;
			case INVOKE_FUNCTION:
				Object[] arguments = _frame[i].getArguments();
				String functionName = (String) arguments[0];
				Instruction[] function = _vm.getFunction(functionName);
				ExecutionFrame functionFrame = new ExecutionFrame(_vm, function, _stack);
				functionFrame.execute();
				break;
			case PRINT:
				_vm._out.println(_stack.pop().toString());
				break;
			case RETURN:
				return;
			}
		}
	}

}
